<!--
 * @Descripttion: 图片上传
 * @version:
 * @Author: huzhushan@126.com
 * @Date: 2021-10-13 09:15:23
 * @LastEditors: huzhushan@126.com
 * @LastEditTime: 2022-03-23 15:20:44
-->
<template>
  <div class="upload-image">
    <draggable
      v-model="uploadedList"
      class="el-upload-list el-upload-list--picture-card"
      tag="ul"
      :animation="150"
      ghost-class="ghost"
      @update="handleSortChange"
      @choose="showActions = false"
      @unchoose="showActions = true"
    >
      <li
        v-for="file in uploadedList"
        :key="file.uid"
        class="el-upload-list__item"
      >
        <img class="pic" :src="checkImg(file) ? file.url : getIcon(file)" alt />
        <label class="el-upload-list__item-status-label">
          <i class="el-icon-upload-success el-icon-check"></i>
        </label>
        <span
          :class="{ hide: !showActions }"
          class="el-upload-list__item-actions"
          @mousedown="showActions = false"
          @mouseup="showActions = true"
        >
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in"></i>
          </span>
          <span class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </li>
    </draggable>
    <el-upload
      ref="upload"
      :action="`${VUE_APP_BASE_URL}/api/system/oss/upload`"
      list-type="picture-card"
      :file-list="fileList"
      :show-file-list="false"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadFailed"
      :before-upload="beforeUpload"
      :on-exceed="handleExceed"
      :on-progress="handleChange"
      :headers="headers"
      v-bind="$attrs"
      :class="isHideUploadButton ? 'hide' : ''"
    >
      <i class="el-icon-plus" />
      <!-- <template #file="{file}">
        <img class="pic" :src="checkImg(file) ? file.url : getIcon(file)" alt />
        <label class="el-upload-list__item-status-label">
          <i class="el-icon-upload-success el-icon-check"></i>
        </label>
        <span class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in"></i>
          </span>
          <span class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </template> -->
      <div slot="tip" class="el-upload__tip">
        <slot name="tip" />
      </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible" width="80%">
      <img
        style="max-width: 100%; max-height: 100%"
        :src="dialogImageUrl"
        alt
      />
    </el-dialog>
  </div>
</template>

<script>
import Draggable from 'vuedraggable'
import { getToken } from '@/utils/auth'
export default {
  name: 'UploadFile',
  components: {
    Draggable,
  },
  props: {
    accept: {
      type: String,
      default: '',
    },
    fileSize: {
      type: Number,
      default: 0,
    },
    fileList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      showActions: true,
      VUE_APP_BASE_URL: process.env.VUE_APP_BASE_URL
        ? process.env.VUE_APP_BASE_URL
        : '',
      dialogImageUrl: '',
      dialogVisible: false,
      uploadedLength: 0,
      uploadedList: [],
      headers: {
        Authorization: getToken(),
      },
      uploading: false,
      fileType: {
        doc: 'doc',
        docx: 'doc',
        ppt: 'ppt',
        pptx: 'ppt',
        xls: 'xls',
        xlsx: 'xls',
        pdf: 'pdf',
        txt: 'txt',
        png: 'pic',
        jpg: 'pic',
        jpeg: 'pic',
        gif: 'pic',
        svg: 'pic',
        zip: 'zip',
        rar: 'zip',
        '7z': 'zip',
        [undefined]: 'undefined',
      },
    }
  },
  computed: {
    isHideUploadButton() {
      return this.uploadedLength >= this.$attrs.limit
    },
    acceptArr() {
      const accept = this.accept.trim()
      const arr = accept ? accept.toLowerCase().split(',') : []
      const res = arr.map(item => item.trim())

      return res
    },
  },
  watch: {
    'fileList.length'(v) {
      this.uploadedLength = v
      this.uploadedList = this.fileList
    },
  },
  mounted() {},
  methods: {
    getFileTypeIcon(extname) {
      return require(`@/components/UploadFile/file-type-icons/${this.fileType[extname]}.png`)
    },
    // 获取文件后缀名
    getExtname(name) {
      if (!name) return ''
      return name.substr(name.lastIndexOf('.') + 1).toLowerCase()
    },
    /** 校验文件类型
     * @Descripttion:
     * @Author: zsen.hu@uni-chain.com
     * @param {Object} file
     * @return {*}
     */
    checkFileType(file) {
      const extname = this.getExtname(file.name)
      return (
        this.acceptArr.length === 0 || this.acceptArr.includes(`.${extname}`)
      )
    },

    checkImg(file) {
      const extname = this.getExtname(file.name)
      return ['.jpg', '.jpeg', '.png', '.gif', '.svg'].includes(`.${extname}`)
    },
    getIcon(file) {
      const extname = this.getExtname(file.name)
      return this.getFileTypeIcon(extname)
    },
    emitUploadedList() {
      const uploadedList = this.$refs.upload.uploadFiles.map(item => {
        if (item.response) {
          const { fileName, src, domain } = item.response.data
          return {
            name: fileName,
            url: src,
            domain,
          }
        } else {
          return {
            name: item.name,
            url: item.url,
          }
        }
      })

      this.uploadedLength = uploadedList.length
      this.uploadedList = this.$refs.upload.uploadFiles.map(
        ({ uid, url, name }) => ({
          uid,
          url,
          name,
        })
      )

      this.$emit('change', uploadedList)
    },
    handleUploadFailed(err, file, fileList) {
      try {
        const { msg } = JSON.parse(err.message)
        this.$message.error(msg)
      } catch (err) {}
    },
    handleUploadSuccess(res, file, fileList) {
      const { code, message } = file.response
      if (+code !== 200) {
        this.$message.error(message)
        this.handleRemove(file)
        return
      }
      // 回调
      this.emitUploadedList()
    },
    handleRemove(file) {
      this.$refs.upload.uploadFiles = this.$refs.upload.uploadFiles.filter(
        item => item.uid !== file.uid
      )

      // 回调
      this.emitUploadedList()
    },
    beforeUpload(file) {
      if (!this.checkFileType(file)) {
        this.$message.error('请选择正确格式的文件!')
        return false
      }

      const isLimitSize =
        !this.fileSize || file.size / 1024 / 1024 <= this.fileSize

      if (!isLimitSize) {
        this.$message.error('文件大小不能超过' + this.fileSize + 'M!')
        return false
      }
      return true
    },
    handlePictureCardPreview(file) {
      if (this.checkImg(file)) {
        this.dialogImageUrl = file.url
        this.dialogVisible = true
      } else {
        window.open(file.url)
      }
    },

    handleExceed(files, fileList) {
      this.$message.warning(`最多只能上传 ${this.$attrs.limit} 个文件`)
    },
    handleChange(ev) {
      this.uploading = ev.percent < 100
    },
    handleSortChange() {
      const _arr = this.uploadedList.map(item => item.uid)

      this.$refs.upload.uploadFiles.sort(
        (a, b) => _arr.indexOf(a.uid) - _arr.indexOf(b.uid)
      )

      this.emitUploadedList()
    },
  },
}
</script>

<style lang="scss" scoped>
.upload-image {
  .hide {
    ::v-deep .el-upload {
      display: none;
    }
  }
  ::v-deep .el-upload {
    border: 1px dashed #c0ccda;
    width: 60px;
    height: 60px;
    line-height: 60px;
    border-radius: 4px;
    float: left;
    margin-right: 20px;
    overflow: hidden;
  }
  ::v-deep .el-upload-list--picture-card {
    float: left;
    margin-right: 0;
    overflow: hidden;
    &:empty {
      display: none;
    }
    .el-upload-list__item {
      width: 60px;
      height: 60px;
      border: 1px dashed #c0ccda;
    }
  }
  ::v-deep {
    .el-upload-list__item.is-success:hover .el-upload-list__item-status-label,
    .el-upload-list__item.is-success:focus .el-upload-list__item-status-label {
      display: block;
    }

    .el-upload-list--picture-card
      .el-upload-list__item:hover
      .el-upload-list__item-status-label {
      display: none;
    }
    .el-upload-list__item-actions {
      cursor: move;
      user-select: none;
      &.hide {
        opacity: 0;
      }
    }
  }

  .el-upload__tip {
    float: left;
    line-height: 20px;
    color: #a4a4a4;
  }
  .pic {
    position: absolute;
    max-width: calc(100% - 2px);
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    &.el-icon-document {
      font-size: 40px;
      color: #777;
    }
  }
  .el-icon-plus {
    font-size: 20px;
  }
}
</style>
<style lang="scss">
.upload-image {
  .ghost {
    border: dashed 2px #f00 !important;
  }
}
</style>
